﻿#pragma once

#include "Ability/EditorAbilityViewModel.h"
#include "EditorSceneOutlineAbilityModel.h"
#include "EditorSceneOutlineAbilityViewModel.m.h"

class REditorEditableTextViewModel;

RCLASS()
class REditorSceneOutlineAbilityViewModel : public REditorAbilityViewModel
{

    ROBJECT

public:
    virtual void BindModel(TSharedObjectPtr<REditorAbilityModel> InModel) ;
    virtual TSharedObjectPtr<RTexture2D> GetIcon() const override;
    virtual TSharedObjectPtr<RTexture2D> GetHighlightIcon() const override;


protected:
    TWeakObjectPtr<REditorSceneOutlineAbilityModel> Model;
    TSharedObjectPtr<RTexture2D> Icon;
    TSharedObjectPtr<RTexture2D> HighlightIcon;

    TSharedObjectPtr<RTexture2D> CollapsedIcon;
    TSharedObjectPtr<RTexture2D> ExpandedIcon;
public:
    bool HasNodes() const ;

    int64_t GetVisibleNodeNum() const;
    const float LineHeight = 20;
    float GetNodeDepth(int64_t Index) const;
    TSharedObjectPtr<RTexture2D> GetNodeIcon(int64_t Index) const;
    int64_t FontSize = 16;
    CString GetNodeText(int64_t Index) const;
    void OnLineClicked(int64_t Index);
    bool HasSubNode(int64_t Index) const;

    bool HaveHoveredNode() const;
    int64_t GetHoveredNodeIndex() const;
    void SetHoveredNodeIndex(int64_t Index);

    bool HaveSelectedNode() const;
    int64_t GetSelectedNodeIndex() const;
    void SetSelectedNodeIndex(int64_t Index);

    TDelegate<void> OnNodeTreeChanged;

    void AddNewNode();
    void DeleteFocusedNode();
    void RenameFocusedNode();
protected:
    int64_t HoveredNodeIndex=-1;
    int64_t SelectedNodeIndex=-1;

    struct SOutlineNode
    {
        //节点/场景
        TSharedObjectPtr<RObject> SceneNode;
        int64_t Depth;
        bool bIsExpanded;
        //index in the visible nodes
        //VisibleIndex impossible to be -1
        //because if a node is invisible, will not create a SOutlineNode for it
        //so VisibleIndex is always valid
        int64_t VisibleIndex=-1; 

        TVector<std::shared_ptr<SOutlineNode>> Children;
    };

    //outline tree
    std::shared_ptr<SOutlineNode> RootNode;
    
    //visible nodes in order
    TVector<std::shared_ptr<SOutlineNode>>  VisibleNodes;

    void UpdateNodeTree();


public:
    int64_t GetEditingNodeIndex() const
    {
        return EditingListIndex;
    }

    bool HasEditingNameError()
    {
        return !EditingNameError.IsEmpty();
    }

    CString GetEditingNameError()
    {
        return EditingNameError;
    }

    TSharedObjectPtr<REditorEditableTextViewModel> GetNameEditViewModel()
    {
        return NameEditViewModel;
    }
protected:
    CString EditingNameError;
    int64_t EditingListIndex=-1;
    TSharedObjectPtr<REditorEditableTextViewModel> NameEditViewModel;

    CString IsValidEditingName(const CString& InNodeName);
};